import json
import time
from functools import wraps

from flask import Flask, jsonify, request
from flask_redis import FlaskRedis
from flask_sqlalchemy import SQLAlchemy

from json_encoder import extended_encoder

app = Flask(__name__)
app.config.from_object('config')
db = SQLAlchemy(app)
redis_client = FlaskRedis(app)
# db = SQLAlchemy(app, session_options={'autocommit': True})

from models import *

with app.app_context():  # 添加这一句，否则会报数据库找不到application和context错误
    db.init_app(app)  # 初始化db
    # db.create_all()


def cost_time(func):
    @wraps(func)
    def wraper(*args, **kwargs):
        start = time.time()
        t = func(*args, **kwargs)
        print("%s tooks time: %f", func.__name__, time.time() - start)
        return t

    return wraper


@app.route('/query/redis', methods=['GET'])
@cost_time
def redis_query():
    cache_res = redis_client.get('test')
    if cache_res:
        print('hit redis cache')
        return jsonify(json.loads(cache_res))
    else:
        if request.args.get('all'):
            sts = Student.query.all()
            score_q = t_score.select()
            scs = db.engine.execute(score_q).fetchall()
        else:
            sts = Student.query.filter_by(gender='男').all()
            # 没有主键的表
            score_q = t_score.select().where(t_score.c.score > 0).where(t_score.c.course == '语文')
            scs = db.engine.execute(score_q).fetchall()
        res = {'学生': list(map(lambda _: _.to_dict(), sts)),
               '成绩': list(map(lambda _: dict(zip(_.iterkeys(), _.itervalues())), scs))}
        redis_client.set('test', json.dumps(res))
        return jsonify(res)


@app.route('/query', methods=['GET'])
def query():
    if request.args.get('all'):
        sts = Student.query.all()
        score_q = t_score.select()
        scs = db.engine.execute(score_q).fetchall()
    else:
        sts = Student.query.filter_by(gender='男').all()
        # 没有主键的表
        score_q = t_score.select().where(t_score.c.score > 0).where(t_score.c.course == '语文')
        scs = db.engine.execute(score_q).fetchall()
    res = {'学生': list(map(lambda _: _.to_dict(), sts)),
           '成绩': list(map(lambda _: dict(zip(_.iterkeys(), _.itervalues())), scs))}
    return jsonify(res)


@app.route('/query/raw')
def query_raw():
    res = db.engine \
        .execute('select * from student a left join score b on a.id=b.student_id') \
        .fetchall()
    res = list(map(lambda _: dict(zip(_.iterkeys(), map(extended_encoder, _.itervalues()))), res))
    return jsonify(res)


@app.route('/add', methods=['POST'])
def add():
    d = request.json
    std = Student(name=d['name'], birth=d['birth'], gender=d['gender'])
    db.session.add(std)
    # 一般都记得手动提交
    db.session.commit()
    return jsonify({'success': True})


@app.route('/update', methods=['POST'])
def update():
    old_std = Student.query.filter_by(name='test2').first()
    print(json.dumps(old_std.to_dict(), indent=2, ensure_ascii=False))
    old_std.gender = '男'
    db.session.commit()
    new_std = Student.query.filter_by(name='test2').first()
    return jsonify(new_std.to_dict())


@app.route('/delete/<name>', methods=['DELETE'])
def delete(name):
    std = Student.query.filter_by(name=name).first()
    db.session.delete(std)
    db.session.commit()
    return jsonify({'success': True})


if __name__ == '__main__':
    app.run()
